home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / umddvi / dev / dmdslave.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  21KB  |  1,177 lines

  1. /*
  2.  * Typesetter/Terminal Emulator for the DMD 5620
  3.  *
  4.  *    Lou Salkind
  5.  *    New York University
  6.  *    Thu Apr  2 01:21:09 EST 1987
  7.  *
  8.  * This program was inspired by the DMD proof program
  9.  * and the Impress typesetting language.  It is used by
  10.  * the TeX DVIDMD driver.
  11.  */
  12.  
  13. #include <jerq.h>
  14. #include "layer.h"
  15. #include "font.h"
  16. #include "dmdcodes.h"
  17.  
  18. #define    MAXFAMILY    128    /* number of different fonts */
  19. #define    MAXFONTNAME    16    /* maximum font string */
  20. #define    PAGECHAR    8192    /* buffered characters to save */
  21. #define    MAXPAGE        127
  22.  
  23. #define    SCROLLSIZE    20    /* scrolling border */
  24. #define    PAGEPIXELS    1010    /* XXX - length of page (should be an argument) */
  25. #define    NEWLINESIZE    16
  26. #define CURSOR '\01'    /* cursor char in font */
  27. #define    LINEBUFSIZE 100
  28.  
  29. #define MOVED 256
  30.  
  31. #ifdef    PAGECHAR
  32. /* treatment of input characters */
  33. #define    CHAR_DISCARD    0
  34. #define    CHAR_STORE    1
  35. #define    CHAR_FETCH    2
  36.  
  37. int savechars;
  38. char savebuf[PAGECHAR];
  39. char *saveptr;
  40. #endif
  41.  
  42. #define    RoundUp(a, b)    (((a) + (b) - 1) & ~((b) - 1))
  43.  
  44. #ifdef    MPX
  45. #undef    cursinhibit
  46. #undef    cursallow
  47. #define    cursinhibit()    {}
  48. #define    cursallow()    {}
  49. #endif
  50.  
  51. static Texture16 prompt = {
  52.     0x0000, 0x0000, 0x0000, 0x322E, 0x4B69, 0x4369, 0x42A9, 0x42A9,
  53.     0x42A9, 0x4229, 0x4229, 0x4229, 0x322E, 0x0000, 0x0000, 0x0000
  54. };
  55.  
  56. Point fudge = {5, 3};    /* DAG - offsets from corners */
  57.  
  58. int dotypeset;    /* 1==typesetter, 0==terminal */
  59. int cursvis;    /* is cursor visible */
  60. Point org;    /* current origin */
  61. Point typeorg;    /* current typesetter origin */
  62. Point curpt;    /* current typesetter point relative to origin */
  63. Point curpos;    /* current ascii terminal position */
  64.  
  65. struct line {
  66.     char buf[LINEBUFSIZE];
  67.     char *bufp;
  68. };
  69.  
  70. struct line line;
  71.  
  72. struct glyph {
  73.     Bitmap    g_bitmap;
  74.     short    g_pxwidth;
  75.     short    g_xoffset;
  76.     short    g_yoffset;
  77. };
  78.  
  79. struct fontinfo {
  80.     char    f_name[MAXFONTNAME];
  81.     struct glyph    f_glyph[128];
  82. };
  83.  
  84. struct fontinfo *ftbl[MAXFAMILY];
  85. struct fontinfo *curfont;
  86. Point inpoint();
  87.  
  88.  
  89. main()
  90. {
  91.     register int c;
  92.  
  93.     resetmode(DMD_TERM);
  94. #ifdef    MPX
  95.     P->state |= RESHAPED;    /* set window parameters */
  96. #else
  97.     Drect = inset(Drect, 2);
  98. #endif    /* MPX */
  99.     windowupdate();
  100.     for(;;) {
  101.         c = inchar();
  102.         if (dotypeset)
  103.             typeset(c);
  104.         else {
  105.             if(cursvis)
  106.                 term(CURSOR, 0);    /* undraw cursor */
  107.             term(c, 1);
  108.             while (own()&RCV)
  109.                 term(inchar(), 1);
  110.             term(CURSOR, 0);    /* draw at new spot */
  111.             cursvis = 1;
  112.         }
  113.     }
  114. }
  115.  
  116. /* terminal emulation */
  117. term(c, advance)
  118.     register int c;
  119. {
  120.     register struct line *linep = &line;
  121.     register Point *pp = &curpos;
  122.     register Fontchar *fp;
  123.     Rectangle r;
  124.     Point p;
  125.  
  126.     if (c & 0x80) {
  127.         if (c == DMD_TYPESET) {
  128.             resetmode(DMD_TYPESET);
  129.             send(DMD_ACK);
  130.             return;
  131.         }
  132.         c &= 0x7F;
  133.     }
  134.     switch(c) {
  135.     default:
  136.         fp = defont.info+c;
  137.         if (fp->width+pp->x >= Drect.corner.x)
  138.             newline(linep, pp);
  139.         p = *pp;
  140.         r.origin.x = fp->x;
  141.         r.corner.x = (fp+1)->x;
  142.         if (advance) {
  143.             r.origin.y = 0;
  144.             r.corner.y = defont.height;
  145.             bitblt(defont.bits, r, &display, p, F_STORE);
  146.             pp->x += fp->width;
  147.             if (linep->bufp < linep->buf+LINEBUFSIZE)
  148.                 *linep->bufp++ = c;
  149.         } else {
  150.             r.origin.y = fp->top;
  151.             r.corner.y = fp->bottom;
  152.             p.y += fp->top;
  153.             bitblt(defont.bits, r, &display, p, F_XOR);
  154.         }
  155.         break;
  156.     case '\n':
  157.         newline(linep, pp);
  158.         break;
  159.     case '\7':
  160.         ringbell();    /* DAG -- should work? */
  161.     case 0:
  162.         break;
  163.     case '\r':
  164.         pp->x=Drect.origin.x+fudge.x;    /* DAG -- changed 5 to fudge.x */
  165.         linep->bufp = linep->buf;
  166.         break;
  167.     case '\013':    /* ^K: reverse linefeed */
  168.         if(pp->y>Drect.origin.y+fudge.y+defont.height)
  169.             pp->y-=NEWLINESIZE;
  170.         break;
  171.     case '\b':
  172.         backspace(linep, pp);
  173.         break;
  174.     case '\014':
  175.         formfeed(linep, pp);
  176.         break;
  177.     case '\t':
  178.         pp->x=nexttab(pp->x);
  179.         if(pp->x>=Drect.corner.x)
  180.             newline(linep, pp);
  181.         if(linep->bufp<linep->buf+LINEBUFSIZE)
  182.             *linep->bufp++=c;
  183.         break;
  184.     }
  185. }
  186.  
  187. /*int eightspaces=8*dispatch[' '].c_wid;*/
  188. int eightspaces=72;
  189.  
  190. nexttab(x)
  191. {
  192.     register int xx = x-Drect.origin.x-fudge.x;
  193.  
  194.     return(xx-(xx%eightspaces)+eightspaces+Drect.origin.x+fudge.x);
  195. }
  196.  
  197. backspace(linep, pp)
  198.     register struct line *linep;
  199.     register Point *pp;
  200. {
  201.     register char *p;
  202.     register int x = Drect.origin.x+fudge.x;
  203.  
  204.     if (linep->bufp>linep->buf) {
  205.         for (p=linep->buf; p<linep->bufp-1; p++)
  206.             if (*p=='\t')
  207.                 x = nexttab(x);
  208.             else
  209.                 x += defont.info[*p].width;
  210.         pp->x = x;
  211.         --linep->bufp;
  212.         if (*p!='\t')
  213.             term(*p, 0);
  214.     }
  215. }
  216.  
  217. newline(linep, pp)
  218.     struct line *linep;
  219.     register Point *pp;
  220. {
  221.     register cursoff=0;
  222.  
  223.     if (pp->y+2*NEWLINESIZE > Drect.corner.y-fudge.y+1) {
  224.         /* weirdness is because the tail of the arrow may be anywhere */
  225.         if (rectXrect(Rect(mouse.xy.x-16, mouse.xy.y-16, mouse.xy.x+16,
  226.                 mouse.xy.y+16), Drect)){
  227.             cursinhibit();
  228.             cursoff++;
  229.         }
  230.         lscroll();
  231.         if(cursoff)
  232.             cursallow();
  233.     } else
  234.         pp->y += NEWLINESIZE;
  235.     pp->x = Drect.origin.x+fudge.x;
  236.     linep->bufp = linep->buf;
  237. }
  238.  
  239. lscroll()
  240. {
  241.     Rectangle r;
  242.  
  243.     r = Drect;
  244.     r.origin.y += NEWLINESIZE;
  245.     bitblt(&display, r, &display, Pt(r.origin.x, r.origin.y-NEWLINESIZE), F_STORE);
  246.     stipple(Rpt(Pt(Drect.origin.x, Drect.corner.y-NEWLINESIZE), Drect.corner));
  247. }
  248.  
  249. formfeed(linep, pp)
  250.     struct line *linep;
  251.     Point *pp;
  252. {
  253.     cursinhibit();
  254.     stipple(Drect);
  255.     cursallow();
  256.     *pp=add(Drect.origin, fudge);
  257.     linep->bufp=linep->buf;
  258. }
  259.  
  260. stipple(r)
  261.     Rectangle r;
  262. {
  263.     cursinhibit();
  264.     rectf(&display, r, F_CLR);
  265.     cursallow();
  266. }
  267.  
  268. /* routines to handle command input */
  269.  
  270. inchar()
  271. {
  272.     register int c;
  273.  
  274. #ifdef    PAGECHAR
  275.     if (savechars == CHAR_FETCH)
  276.         return(*saveptr++ & 0377);
  277. #endif
  278. #ifdef    MPX
  279.     wait(RCV);
  280.     if (P->state&(RESHAPED|MOVED))
  281.         windowupdate();
  282.     c = rcvchar();
  283. #else
  284.     for ( ; ; ) {
  285.         wait(RCV|KBD);
  286.         if (own() & RCV) {
  287.             c = rcvchar();
  288.             break;
  289.         }
  290.         if (!dotypeset)
  291.             send(kbdchar());
  292.     }
  293. #endif    MPX
  294. #ifdef    PAGECHAR
  295.     if (savechars == CHAR_STORE) {
  296.         if (saveptr < &savebuf[PAGECHAR])
  297.             *saveptr++ = c;
  298.         else
  299.             savechars = CHAR_DISCARD;
  300.     }
  301. #endif
  302.     return(c&0377);
  303. }
  304.  
  305. insignchar()
  306. {
  307.     register int c;
  308.  
  309.     c = inchar();
  310.     if (c > 127)
  311.         c -= 256;
  312.     return(c);
  313. }
  314.  
  315. inshort()
  316. {
  317.     register short i;
  318.  
  319.     i = inchar() << 8;
  320.     i |= inchar();
  321.     return(i);
  322. }
  323.  
  324. Point
  325. inpoint()
  326. {
  327.     Point p;
  328.  
  329.     p.x = inshort() + typeorg.x;
  330.     p.y = inshort() + typeorg.y;
  331.     return(p);
  332. }
  333.  
  334. send(c)
  335. {
  336.     char cc = c;
  337.  
  338.     sendnchars(1, &cc);
  339. }
  340.  
  341. /* typesetter emulation */
  342. typeset(c)
  343.     register int c;
  344. {
  345.     register struct glyph *g;
  346.     register Bitmap *b;
  347.     Point pprime;
  348.     int old;
  349.  
  350.     if (c <= 127) {
  351.         if (curfont == 0)
  352.             return;
  353.         g = &curfont->f_glyph[c];
  354.         b = &g->g_bitmap; 
  355.         if (b->base == 0) {
  356.             curpt.x += g->g_pxwidth;
  357.             return;
  358.         }
  359.         pprime = add(curpt, typeorg);
  360.         pprime.x -= g->g_xoffset;
  361.         pprime.y -= g->g_yoffset;
  362.         bitblt(b, b->rect, &display, pprime, F_OR);
  363.         curpt.x += g->g_pxwidth;
  364.         return;
  365.     }
  366.  
  367.     switch (c) {
  368.     case DMD_EXIT:
  369.         bye();
  370.         break;
  371.     case DMD_TERM:
  372. #ifdef    PAGECHAR
  373.         savechars = CHAR_DISCARD;
  374. #endif
  375.         resetmode(DMD_TERM);
  376.         break;
  377.     case DMD_CLEAR:
  378.         stipple(Drect);
  379.         curpos = add(org, fudge);
  380.         break;
  381.     case DMD_TYPESET:
  382.         send(DMD_ACK);
  383.         break;
  384.     case DMD_ASCII:
  385. #ifdef    PAGECHAR
  386.         if (savechars == CHAR_STORE)
  387.             saveptr--;
  388.         old = savechars;
  389.         savechars = CHAR_DISCARD;
  390. #endif
  391.         while (c = inchar())
  392.             term(c, 1);
  393. #ifdef    PAGECHAR
  394.         savechars = old;
  395. #endif
  396.         break;
  397.     case DMD_RULE: {
  398.         short w, h;
  399.         Rectangle r;
  400.  
  401.         w = inshort();
  402.         h = inshort();
  403.         pprime = add(curpt, typeorg);
  404.         pprime.y++;
  405.         r.origin = pprime;
  406.         r.origin.y = pprime.y - h;
  407.         r.corner = pprime;
  408.         r.corner.x = pprime.x + w;
  409.         rectf(&display, r, F_STORE);
  410.         break;
  411.     }
  412.     case DMD_FORW:
  413.         curpt.x++;
  414.         break;
  415.     case DMD_BACK:
  416.         curpt.x--;
  417.         break;
  418.     case DMD_HABS:
  419.         curpt.x = inshort();
  420.         break;
  421.     case DMD_HREL:
  422.         curpt.x += insignchar();
  423.         break;
  424.     case DMD_VABS:
  425.         curpt.y = inshort();
  426.         break;
  427.     case DMD_VREL:
  428.         curpt.y += insignchar();
  429.         break;
  430.     case DMD_PAGE:
  431. #ifdef    PAGECHAR
  432.         saveptr = savebuf;
  433.         savechars = CHAR_STORE;
  434. #endif
  435.         stipple(Drect);
  436.         curpos = add(org, fudge);
  437.         curpt.x = curpt.y = 0;
  438.         break;
  439.     case DMD_ENDPAGE:
  440.         pagecmd();
  441.         break;
  442.     case DMD_SETFONT: {
  443.         int i;
  444.  
  445.         i = inchar();
  446.         if (i < MAXFAMILY)
  447.             curfont = ftbl[i];
  448.         break;
  449.     }
  450.     case DMD_MKFONT:
  451.     case DMD_SGLYPH:
  452.     case DMD_BGLYPH:
  453. #ifdef    PAGECHAR
  454.         if (savechars == CHAR_STORE)
  455.             saveptr--;
  456.         old = savechars;
  457.         savechars = CHAR_DISCARD;
  458. #endif
  459.         if (c == DMD_MKFONT)
  460.             ldfont();
  461.         else
  462.             ldglyph(c);
  463. #ifdef    PAGECHAR
  464.         savechars = old;
  465. #endif
  466.         break;
  467.     case DMD_SEGMENT:
  468.     case DMD_SPLINE:
  469.         define_path(c);
  470.         break;
  471.     case DMD_CIRCLE:
  472.         define_circle();
  473.         break;
  474.     case DMD_ELLIPSE:
  475.         define_ellipse();
  476.         break;
  477.     case DMD_DRAWPATH:
  478.         draw_path();
  479.         break;
  480.     case DMD_FILLPATH:
  481.         fill_path();
  482.         break;
  483.     case DMD_PENSIZE:
  484.         set_pen();
  485.         break;
  486.     default:
  487.         break;
  488.     }
  489. }
  490.  
  491. /* request an index number for a new font */
  492. ldfont()
  493. {
  494.     register struct fontinfo *f;
  495.     register int i, j;
  496.     register int x = -1;
  497.     char name[MAXFONTNAME];
  498.     register char *p;
  499.     char loaded[16];
  500.  
  501.     p = name;
  502.     while (*p++ = inchar())
  503.         if (p >= &name[MAXFONTNAME]) {
  504.             while (inchar())
  505.                 continue;
  506.             break;
  507.         }
  508.     for (i = 0; i < sizeof(loaded); i++)
  509.         loaded[i] = 0;
  510.     /* look for the font... */
  511.     for (i = 0; i < MAXFAMILY; i++) {
  512.         f = ftbl[i];
  513.         if (f && strncmp(f->f_name, name, sizeof(f->f_name)) == 0) {
  514.             for (j = 0; j < 128; j++) {
  515.                 if (f->f_glyph[j].g_bitmap.base)
  516.                     loaded[j>>3] |= 1 << (~j & 07);
  517.             }
  518.             send(i);
  519.             sendnchars(sizeof(loaded), loaded);
  520.             return;
  521.         }
  522.         if (x == -1 && f == 0)
  523.             x = i;
  524.     }
  525.     if (x == -1) {
  526.         send(-1);
  527.         return;
  528.     }
  529.     f = (struct fontinfo *)alloc(sizeof (struct fontinfo));
  530.     if (f == 0) {
  531.         send(-1);
  532.         return;
  533.     }
  534.     ftbl[x] = f;
  535.     strncpy(f->f_name, name, sizeof(f->f_name));
  536.     send(x);
  537.     sendnchars(sizeof(loaded), loaded);
  538. }
  539.  
  540. /* download a particular character in a font */
  541. ldglyph(c)
  542.     int c;
  543. {
  544.     register struct glyph *g;
  545.     register int i, j;
  546.     register char *p;
  547.     short chr, fam, w;
  548.     int words;
  549.     int o;
  550.     short xs, ys;
  551.     int endb;
  552.     static struct glyph gdummy;
  553.  
  554.     w = inshort();
  555.     fam = (w >> 7) & 0177;
  556.     chr = w & 0177;
  557.     if (ftbl[fam])
  558.         g = &(ftbl[fam]->f_glyph[chr]);
  559.     else {
  560.         ftbl[fam] = (struct fontinfo *)alloc(sizeof (struct fontinfo));
  561.         g = ftbl[fam] ? &(ftbl[fam]->f_glyph[chr]) : &gdummy;
  562.     }
  563.  
  564.     if (c == DMD_SGLYPH) {
  565.         g->g_pxwidth = insignchar();
  566.         xs = inchar();
  567.         g->g_xoffset = insignchar();
  568.         ys = inchar();
  569.         g->g_yoffset = insignchar();
  570.     } else {
  571.         g->g_pxwidth = inshort();
  572.         xs = inshort();
  573.         g->g_xoffset = inshort();
  574.         ys = inshort();
  575.         g->g_yoffset = inshort();
  576.     }
  577.     words = RoundUp(xs, WORDSIZE) >> WORDSHIFT;
  578.     o = RoundUp(xs, 8) >> 3;
  579.     endb = words * sizeof(Word);
  580.     if (g->g_bitmap.base)
  581.         free(g->g_bitmap.base);
  582.     if (g == &gdummy || (p = alloc(ys * endb)) == 0) {
  583.         /* skip raster bytes */
  584.         j = o * ys;
  585.         for (i = 0; i < j; i++)
  586.             inchar();
  587.     } else {
  588.         /* read raster here */
  589.         g->g_bitmap.base = (Word *)p;
  590.         g->g_bitmap.width = words;
  591.         g->g_bitmap.rect.origin.x = 0;
  592.         g->g_bitmap.rect.origin.y = 0;
  593.         g->g_bitmap.rect.corner.x = xs;
  594.         g->g_bitmap.rect.corner.y = ys;
  595.         g->g_bitmap._null = 0;
  596.         p = (char *)g->g_bitmap.base;
  597.         for (j = 0; j < ys; j++) {
  598.             for (i = 0; i < o; i++)
  599.                 *p++ = inchar();
  600.             for ( ; i < endb; i++)
  601.                 *p++ = 0;
  602.         }
  603.     }
  604. }
  605.  
  606. /* mouse and keyboard input routines at end of page */
  607.  
  608. static char *b3m[] = {
  609.     "redraw",
  610.     "next",
  611.     "prev",
  612.     "quit",
  613.     "exit",
  614.     NULL
  615. };
  616.  
  617. static Menu menu = { b3m };
  618.  
  619. Texture16 ok = {
  620.      0x1C44, 0x2248, 0x2250, 0x2270,
  621.      0x2248, 0x1C44, 0x0000, 0x0380,
  622.      0x0440, 0x0440, 0x0080, 0x0100,
  623.      0x0100, 0x0100, 0x0000, 0x0100,
  624. };
  625.  
  626. minkbd()
  627. {
  628.     Texture16 *t;
  629.     register int i;
  630.     int oscroll = 0;
  631.     register int inscroll = 0;
  632.     Point selpt;
  633.  
  634.     while (i = wait(KBD|MOUSE|RCV)) {
  635.         if (i&KBD)
  636.             return(kbdchar());
  637.         else if (i&RCV)
  638.             return(rcvchar());
  639.         selpt = mouse.xy;
  640.         i = selpt.x - Drect.origin.x;
  641.         inscroll = 0;
  642.         if (i >= 0 && i < SCROLLSIZE)
  643.             inscroll += 1;
  644.         i = Drect.corner.y - selpt.y;
  645.         if (i >= 0 && i < SCROLLSIZE)
  646.             inscroll += 2;
  647.         if (inscroll != oscroll) {
  648.             cursswitch(inscroll ? &C_crosshair : &prompt);
  649.             oscroll = inscroll;
  650.         }
  651.         switch (inscroll) {
  652.         case 0:
  653.             if (!bttn3())
  654.                 break;
  655.             switch (i = menuhit(&menu, 3)) {
  656.             case -1:
  657.                 break;
  658.             case 4:
  659.                 t = cursswitch(&ok);
  660.                 while (!bttn123()) sleep(1);
  661.                 i = bttn3();
  662.                 while (bttn123()) sleep(1);
  663.                 (void)cursswitch(t);
  664.                 if (i)
  665.                     return('x');
  666.                 break;
  667.             default:
  668.                 return("rnpq"[i]);
  669.             }
  670.             break;
  671.         case 1:
  672.             if (!bttn13())
  673.                 break;
  674.             if (bttn1())
  675.                 typeorg.y -= selpt.y - Drect.origin.y;
  676.             else
  677.                 typeorg.y += selpt.y - Drect.origin.y;
  678.             /* primitive scroll for now */
  679.             while (bttn123());
  680.             return('s');
  681.         case 2:
  682.             if (!bttn13())
  683.                 break;
  684.             if (bttn1())
  685.                 typeorg.x -= selpt.x - Drect.origin.x;
  686.             else
  687.                 typeorg.x += selpt.x - Drect.origin.x;
  688.             /* primitive scroll for now */
  689.             while (bttn123());
  690.             return('s');
  691.         case 3:
  692.             if (bttn1())
  693.                 return('n');
  694.             else if (bttn2())
  695.                 return('r');
  696.             else if (bttn3())
  697.                 return('p');
  698.             break;
  699.         }
  700.         sleep(1);
  701.     }
  702.     /*NOT REACHED*/
  703. }
  704.  
  705. pagecmd()
  706. {
  707.     register int i;
  708.     register Texture16 *t;
  709.     int cmd;
  710.     Point p1, p2;
  711.     int redraw;
  712. #ifdef    PAGECHAR
  713.     int pagesaved;
  714.     char buf[40];
  715.  
  716.     pagesaved = savechars != CHAR_DISCARD;
  717. #endif
  718.     t = cursswitch(&prompt);
  719. pgstart:
  720.     redraw = 0;
  721.     /*
  722.      * draw outlines of scroll bars.  We will draw
  723.      * the whole lines when we can't write in the
  724.      * scroll area, but for now, do it this way.
  725.      */
  726.     p1 = Drect.origin;
  727.     p1.x += SCROLLSIZE;
  728.     p2.x = p1.x;
  729.     p2.y = p1.y + SCROLLSIZE;
  730.     segment(&display, p1, p2, F_STORE);
  731.     p1.y = Drect.corner.y - 2*SCROLLSIZE;
  732.     p2.y = Drect.corner.y;
  733.     segment(&display, p1, p2, F_STORE);
  734.     p1.y = Drect.corner.y - SCROLLSIZE;
  735.     p2.y = p1.y;
  736.     p1.x = Drect.origin.x;
  737.     p2.x = p1.x + 2*SCROLLSIZE;
  738.     segment(&display, p1, p2, F_STORE);
  739.     p1.x = Drect.corner.x - SCROLLSIZE;
  740.     p2.x = Drect.corner.x;
  741.     segment(&display, p1, p2, F_STORE);
  742. #ifdef    PAGECHAR
  743.     savechars = CHAR_DISCARD;
  744. #ifdef    DEBUG
  745.     sprintf(buf, "%d", saveptr-savebuf);
  746.     p1 = org;
  747.     p1.x += 20;
  748.     p1.y += 20;
  749.     string(&defont, buf, &display, p1, F_XOR);
  750. #endif
  751. #endif
  752.     switch (cmd = minkbd()) {
  753.     case 0177:
  754.     case 04:
  755.     case 'q':
  756.         send(DMD_EXIT);
  757.         resetmode(DMD_TERM);
  758.         t = 0;
  759.         break;
  760.     case 'x':
  761.         send(DMD_EXIT);
  762.         bye();
  763.         break;
  764.     case 'r':
  765.     case '\f':
  766.         typeorg = org;
  767.         /* fall into... */
  768.     case 's':
  769.         redraw = 1;
  770.         break;
  771.     case 'n':
  772.     case ' ':
  773.         typeorg.y -= Drect.corner.y - Drect.origin.y;
  774.         if (org.y - typeorg.y < PAGEPIXELS) {
  775.             redraw = 1;
  776.             break;
  777.         }
  778.         /* fall into... */
  779.     case '+':
  780.     case '\r':
  781.     case '\n':
  782.         typeorg = org;
  783.         send(DMD_PAGE);
  784.         send(1);
  785.         break;
  786.     case 'p':
  787.         typeorg.y += Drect.corner.y - Drect.origin.y;
  788.         if (org.y >= typeorg.y) {
  789.             redraw = 1;
  790.             break;
  791.         }
  792.         /* fall into... */
  793.     case '-':
  794.         typeorg = org;
  795.         send(DMD_PAGE);
  796.         send(-1);
  797.         break;
  798.     default:
  799.     /*    ringbell(); */
  800.         goto pgstart;
  801.     }
  802.     if (redraw) {
  803. #ifdef    PAGECHAR
  804.         if (pagesaved) {
  805. #ifdef    MPX
  806.             if (P->state&(RESHAPED|MOVED))
  807.                 windowupdate();
  808. #endif
  809.             typeset(DMD_PAGE);
  810.             saveptr = savebuf;
  811.             savechars = CHAR_FETCH;
  812.             while ((i = inchar()) != DMD_ENDPAGE)
  813.                 typeset(i);
  814.             (void)cursswitch(&prompt);
  815.             goto pgstart;
  816.         }
  817. #endif
  818.         send(DMD_PAGE);
  819.         send(0);
  820.     }
  821.     (void)cursswitch(t);
  822. }
  823.  
  824. inkbd()
  825. {
  826.     wait(RCV|KBD);
  827.     return((own()&KBD)? kbdchar():rcvchar());
  828. }
  829.  
  830. bye()
  831. {
  832.     register int i;
  833.  
  834.     for (i = 0; i < MAXFAMILY; i++) {
  835.         if (ftbl[i])
  836.             freefont(ftbl[i]);
  837.     }
  838.     exit();
  839. }
  840.  
  841. freefont(f)
  842.     struct fontinfo *f;
  843. {
  844.     struct glyph *g;
  845.  
  846.     for (g = f->f_glyph; g < &f->f_glyph[128]; g++)
  847.         if (g->g_bitmap.base)
  848.             free((char *)g->g_bitmap.base);
  849.     free((char *)f);
  850. }
  851.  
  852. #ifdef    notdef
  853. edit(s)
  854.     char *s;
  855. {
  856.     char buf[40];
  857.     Point p;
  858.     int c;
  859.     register i;
  860.  
  861.     strcpy(buf, s);
  862.     p = mouse.xy;
  863.     disp(buf, p);
  864.     for(i = strlen(buf); (c = inkbd()) != '\r';)
  865.     {
  866.         disp(buf, p);
  867.         p = mouse.xy;
  868.         switch(c)
  869.         {
  870.         case '\b':
  871.             if((buf[i] != ' ') && (i > 0))
  872.                 buf[--i] = 0;
  873.             break;
  874.         case '@':
  875.             while(buf[i] != ' ') i--;
  876.             buf[++i] = 0;
  877.             break;
  878.         default:
  879.             buf[i++] = c;
  880.             buf[i] = 0;
  881.             break;
  882.         }
  883.         disp(buf, p);
  884.     }
  885.     disp(buf, p);
  886.     strcpy(s, buf);
  887. }
  888.  
  889. disp(s, p)
  890.     char *s;
  891.     Point p;
  892. {
  893.     string(&defont, "\001", &display,
  894.         string(&defont, s, &display, p, F_XOR), F_XOR);
  895. }
  896. #endif
  897.  
  898. resetmode(c)
  899.     int c;
  900. {
  901.     if (c == DMD_TERM) {
  902.         cursvis = dotypeset = 0;
  903. #ifdef    MPX
  904.         request(SEND|RCV);
  905. #else
  906.         request(SEND|RCV|KBD);
  907. #endif
  908.         curpos.x = org.x + fudge.x;
  909.         curpos.y = Drect.corner.y - fudge.y - defont.height;
  910.     } else {
  911.         dotypeset = 1;
  912.         request(SEND|RCV|KBD|MOUSE);
  913.         typeorg = org;
  914.     }
  915. }
  916.  
  917. windowupdate()
  918. {
  919. #ifdef    MPX
  920.     if (P->state&RESHAPED) {
  921. #endif
  922.         org = Drect.origin;
  923.         typeorg = org;
  924.         curpos = add(org, fudge);
  925.         line.bufp = line.buf;
  926.         if (cursvis) {
  927.             term(CURSOR, 0);    /* flip state */
  928.             cursvis = 0;
  929.         }
  930. #ifdef    MPX
  931.     } else {
  932.         curpos = add(sub(curpos, org), Drect.origin);
  933.         typeorg = add(sub(typeorg, org), Drect.origin);
  934.         org = Drect.origin;
  935.     }
  936.     P->state &= ~(MOVED|RESHAPED);
  937. #endif
  938.     artdeco();
  939. }
  940.  
  941. static Texture16 vstripe = {
  942.     0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
  943.     0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
  944.     0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
  945.     0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0
  946. };
  947.  
  948. static Texture16 hstripe = {
  949.     0xffff, 0xffff, 0xffff, 0xffff,
  950.     0x0000, 0x0000, 0x0000, 0x0000,
  951.     0xffff, 0xffff, 0xffff, 0xffff,
  952.     0x0000, 0x0000, 0x0000, 0x0000,
  953. };
  954.  
  955. artdeco()
  956. {
  957.     texture16(&display, Rect(display.rect.origin.x, display.rect.origin.y,
  958.         display.rect.corner.x, Drect.origin.y), &vstripe, F_XOR);
  959.     texture16(&display, Rect(display.rect.origin.x, Drect.origin.y,
  960.         Drect.origin.x, Drect.corner.y), &hstripe, F_XOR);
  961.     texture16(&display, Rect(Drect.corner.x, Drect.origin.y,
  962.         display.rect.corner.x, Drect.corner.y), &hstripe, F_XOR);
  963.     texture16(&display, Rect(display.rect.origin.x, Drect.corner.y,
  964.         display.rect.corner.x, display.rect.corner.y), &vstripe, F_XOR);
  965. }
  966.  
  967. /* graphics support; for now there are some unimplemented operations */
  968.  
  969. #define    MAXPOINTS    60
  970.  
  971. #define    PATH_NONE    -1
  972. #define    PATH_SEGMENT    0
  973. #define    PATH_SPLINE    1
  974. #define    PATH_CIRCLE    2
  975. #define    PATH_ELLIPSE    3
  976.  
  977. int path_type = PATH_NONE;
  978. int pen_size = 1;
  979.  
  980. struct {
  981.     Point c_center;
  982.     Point c_start; 
  983.     Point c_finish; 
  984. } path_circle;
  985.  
  986. struct {
  987.     Point e_center;
  988.     Point e_start;
  989.     Point e_finish;
  990.     short e_xradius;
  991.     short e_yradius;
  992. } path_ellipse;
  993.  
  994. Point path_pts[MAXPOINTS+2];
  995. int path_len;
  996.  
  997. define_path(c)
  998. {
  999.     register int i, n;
  1000.     register Point *pp;
  1001.  
  1002.     path_type = (c==DMD_SEGMENT) ? PATH_SEGMENT : PATH_SPLINE;
  1003.     n = inshort();
  1004.     path_len = n;
  1005.     if (path_len > MAXPOINTS) {
  1006.         path_len = MAXPOINTS;
  1007.         for (i = path_len; i < n; i++)
  1008.             (void)inpoint();
  1009.     }
  1010.     pp = &path_pts[1];
  1011.     for (i = 0; i < path_len; i++)
  1012.         *pp++ = inpoint();
  1013. }
  1014.  
  1015. define_circle()
  1016. {
  1017.     path_circle.c_center = inpoint();
  1018.     path_circle.c_start = inpoint();
  1019.     path_circle.c_finish = inpoint();
  1020.     path_type = PATH_CIRCLE;
  1021. }
  1022.  
  1023. define_ellipse()
  1024. {
  1025.     path_ellipse.e_center = inpoint();
  1026.     path_ellipse.e_start = inpoint();
  1027.     path_ellipse.e_finish = inpoint();
  1028.     path_ellipse.e_xradius = inshort();
  1029.     path_ellipse.e_yradius = inshort();
  1030.     path_type = PATH_ELLIPSE;
  1031. }
  1032.  
  1033. draw_path()
  1034. {
  1035.     int rop;
  1036.  
  1037.     rop = inchar();        /* ignore for now */
  1038.     switch (path_type) {
  1039.     case PATH_SEGMENT:
  1040.         draw_segment(F_OR);
  1041.         break;
  1042.     case PATH_SPLINE:
  1043.         draw_spline(F_OR);
  1044.         break;
  1045.     case PATH_CIRCLE:
  1046.         draw_circle(F_OR);
  1047.         break;
  1048.     case PATH_ELLIPSE:
  1049.         draw_ellipse(F_OR);
  1050.         break;
  1051.     }
  1052. }
  1053.  
  1054. fill_path()
  1055. {
  1056.     int rop;
  1057.  
  1058.     rop = inchar();        /* ignore for now */
  1059. }
  1060.  
  1061. set_pen()
  1062. {
  1063.     int i = inchar();
  1064.  
  1065.     if (i < 1)
  1066.         i = 1;
  1067.     pen_size = i;
  1068. }
  1069.  
  1070. /* draw a spline path */
  1071. draw_spline(f)
  1072.     int f;
  1073. {
  1074.     register Point *pp = path_pts;
  1075.     register long w, t1, t2, t3, scale=1000; 
  1076.     register int i, j, steps=10; 
  1077.     int n = path_len + 1;
  1078.     Point p, q;
  1079.  
  1080.     pp[0] = pp[1];
  1081.     pp[n] = pp[n-1];
  1082.     p = pp[0];
  1083.     for (i = 0; i < n-1; i++) {
  1084.         for (j = 0; j < steps; j++) {
  1085.             w = scale * j / steps;
  1086.             t1 = w * w / (2 * scale);
  1087.             w = w - scale/2;
  1088.             t2 = 3*scale/4 - w * w / scale;
  1089.             w = w - scale/2;
  1090.             t3 = w * w / (2*scale);
  1091.             q.x = (t1*pp[i+2].x + t2*pp[i+1].x + 
  1092.                 t3*pp[i].x + scale/2) / scale;
  1093.             q.y = (t1*pp[i+2].y + t2*pp[i+1].y + 
  1094.                 t3*pp[i].y + scale/2) / scale;
  1095.             line_btw(p, q, f);
  1096.             p = q;
  1097.         }
  1098.     }
  1099. }
  1100.  
  1101. /* draw a segment path */
  1102. draw_segment(f)
  1103.     int f;
  1104. {
  1105.     register Point *pp;
  1106.     register int i;
  1107.  
  1108.     pp = &path_pts[1];
  1109.     if (path_len == 1) {
  1110.         if (pen_size > 1)
  1111.             disc(&display, pp[0], pen_size, f);
  1112.         else
  1113.             point(&display, pp[0], f);
  1114.     } else {
  1115.         for (i = 1; i < path_len; i++) {
  1116.             line_btw(pp[0], pp[1], f);
  1117.             pp++;
  1118.         }
  1119.     }
  1120. }
  1121.  
  1122. draw_circle(f)
  1123.     int f;
  1124. {
  1125.     /* ignore pen size for now */
  1126.  
  1127.     if (path_circle.c_center.x == path_circle.c_finish.x &&
  1128.         path_circle.c_center.y == path_circle.c_finish.y) {
  1129.         circle(&display, path_circle.c_center, path_circle.c_start.x, f);
  1130.     } else {
  1131.         arc(&display, path_circle.c_center, path_circle.c_start,
  1132.             path_circle.c_finish, f);
  1133.     }
  1134. }
  1135.  
  1136. draw_ellipse(f)
  1137.     int f;
  1138. {
  1139.     /* ignore pen size for now */
  1140.  
  1141.     if (path_ellipse.e_center.x == path_ellipse.e_finish.x &&
  1142.         path_ellipse.e_center.y == path_ellipse.e_finish.y) {
  1143.         ellipse(&display, path_ellipse.e_center, path_ellipse.e_xradius,
  1144.             path_ellipse.e_yradius, f);
  1145.     } else {
  1146.         elarc(&display, path_ellipse.e_center, path_ellipse.e_xradius,
  1147.             path_ellipse.e_yradius, path_ellipse.e_start,
  1148.             path_ellipse.e_finish, f);
  1149.     }
  1150. }
  1151.  
  1152. /* Draw a line on the screen.  */
  1153. line_btw(p0, p1, rop)
  1154.     Point p0, p1;
  1155. {
  1156.     register int i;
  1157.     register int incx;
  1158.  
  1159.     if (abs(p1.y-p0.y) > abs(p1.x-p0.x)) {
  1160.         incx = 1;
  1161.         p0.x -= pen_size/2;
  1162.         p1.x -= pen_size/2;
  1163.     } else {
  1164.         incx = 0;
  1165.         p0.y -= pen_size/2;
  1166.         p1.y -= pen_size/2;
  1167.     }
  1168.     for (i = 0; i < pen_size; i++) {
  1169.         segment(&display, p0, p1, rop);
  1170.         if (incx) {
  1171.             p0.x++; p1.x++;
  1172.         } else {
  1173.             p0.y++; p1.y++;
  1174.         }
  1175.     }
  1176. }
  1177.